﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.ServiceModel;

namespace Hydra.Core
{
    [ServiceBehavior(
        IncludeExceptionDetailInFaults = true,
        InstanceContextMode = InstanceContextMode.Single,
        ConcurrencyMode = ConcurrencyMode.Single)]
    internal class HydraService : IHydraService, IHydraCallback
    {
        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        private readonly IDictionary<string, OperationContext> _listeners = new Dictionary<string, OperationContext>();

        public void Write(string message)
        {
            log.InfoFormat("[App] " + message);
        }

        public void Register()
        {
            _listeners.Add(OperationContext.Current.SessionId, OperationContext.Current);
            log.Info("Target process has been registered, sid=" + OperationContext.Current.SessionId);
        }

        public void Unregister()
        {
            _listeners.Remove(OperationContext.Current.SessionId);
            log.Info("Target process has been unregistered, sid=" + OperationContext.Current.SessionId);
        }

        public void ApplyDetours(byte[] assembly)
        {
            if (_listeners.Count == 0)
                throw new ApplicationException("No client has been registered.");

            _listeners.First().Value.GetCallbackChannel<IHydraCallback>().ApplyDetours(assembly);
            log.Info("Transfer detours to target process");
        }

        public void ReleaseDetours()
        {
            if (_listeners.Count == 0)
                throw new ApplicationException("No client has been registered.");

            _listeners.First().Value.GetCallbackChannel<IHydraCallback>().ReleaseDetours();
            log.Info("Release detours from target process");
        }
    }
}